/*
Creation date:	from 29/04/2003 to 01/04/2003

Autor:			Mountaniol Vsevolod <sebastian@vboxcomm.com>

File:			updater.c

Description:	Create updates for XLT / XR1 systems. 
                Also apply update on target machines.
*/

#if 0
    #include <sys/types.h> 	/* open, stat */
    #include <sys/stat.h> 	/* open, stat */
    #include <fcntl.h> 		/* open, stat */
    #include <unistd.h>		/* close, stat, mmap, readdir */
    #include <sys/mman.h>	/* mmap */
    #include <dirent.h>		/* readdir */

    #include <stdio.h>		/* ead */
    #include <errno.h>		/* errors */
    #include <string.h>		/* strcpy, str* */
    #include <stdlib.h>		/* malloc */
    #include <zlib.h>

#endif /* 0 */

#include "updater.h"
#include "updater.types.h"
#include "updater.errors.h"
#include "updater.utils.h"
#include "updater.w.h"
#include "updater.w.file.h"
#include "updater.w.memory.h"




/*	functions prototypes */

void print_usage()
{
    ENTRY();
    PRINT("Usage: updater 'action (c | d | l | m | n)' 'update_file' ['spec_file' | 'name' | 'description']\n");
    PRINT("action: c - compress files. Names of files will read from 'spec_file'. Result file is 'update_file'\n");
    PRINT("action: d - decompress file 'update_file' .\n");
    PRINT("action: h - header of 'update_file': description, name, minor-major .\n");
    PRINT("action: l - list of 'update_file' .\n");
    PRINT("action: n - write 'name' of update into 'update_file' .\n");
    PRINT("action: m - write 'description' of update into 'update_file' .\n");
    RETURNVOID();
}



#ifdef DEBUG
/*
    FUNCTION:	PrintFileList
    IN:			struct flist *
    OUT:		nothing

    Get linked list of file names.
    Print file names.
    For debug only.
 */


void PrintFileList(ucore_t * ps_ucore)
{
    file_list_t * ps_fl_copy = ps_ucore->file_list;

    ENTRY();

    if (ps_fl_copy == NULL)
    {
        PRINT("wrong argument\n");
        RETURNVOID();
    }

    while (ps_fl_copy != NULL)
    {
        PRINT("file: %s\n",ps_fl_copy->file_name);
        ps_fl_copy = ps_fl_copy->next;
    }

    RETURNVOID();

}
#endif /* DEBUG */

/*
    FUNCTION:	list_files
    IN:			file name
    OUT:		status
    Test file. 
    If the file is update it prints list of files.
*/
#ifdef BE_VERBOSE
INT list_files(CHAR * pc_file_name)
{
    FD_T * ps_fd;
    size_t i_offset = 0;
    STAT_T * ps_st;
    INT i_rv;
    packet_header_t s_pheader;
    struct file_header s_fh;
    struct file_header s_fh_update;

    ENTRY();

    ps_st = w_new_stat();

    if (pc_file_name == NULL)
    {
        RETURN( - EINVAL );
    }

    i_rv = w_stat(pc_file_name, ps_st);
    if (i_rv < 0 )
    {
        w_free_stat(ps_st);
        PERROR("stat is wrong! ");
        RETURN( - EINVAL );
    }

    ps_fd = w_open (pc_file_name, W_O_RDONLY);

    if ( w_filestatus( ps_fd ) < 0)
    {
        w_free_stat(ps_st);

        PERROR("Can't open file");
        RETURN( - EIO );
    }

    i_rv = w_read(ps_fd, (CHAR *) &s_pheader, sizeof(packet_header_t) );

    if (i_rv != sizeof(packet_header_t))
    {
        PERROR("Can't read update header");
    }

    /*	TODO - check here CBTSUM  */
    /*
    if ( CHECK_SINGATURE(&fh_update.singature) != 0) {
      PRINT("Wrong singature of update\n");
      PRINT("\n\nSingature is: %s when good singature is %s\n", fh_update.singature, SINGATURE);
      RETURN( - ECANCELED );
    }
    */

    PRINT("Update packet: %s\n", s_pheader.name);

    if (CHECK_FLAG(s_fh_update.flags, UPD_HAS_PREINSTALL))
    {
        PRINT("Update has install script\n");
    }

    PRINT("Update major-minor: %i-%i\n", (int) s_pheader.major, (int) s_pheader.minor);
    PRINT("Update description: %s\n", s_fh_update.description);
    PRINT("---------------------------------------------\n");



    do
    {
/*  	rv = read(fd, &offset, sizeof(offset)); 

    if (rv != sizeof(offset)) 
    {
        DD("%s: can't read offset\n", __FUNCTION__);
        continue;
    }
*/
        i_rv = w_read( ps_fd, (CHAR *) &s_fh, sizeof(s_fh) );
        if (i_rv != sizeof(s_fh))
        {
            DD("%s: can't read fh\n", __FUNCTION__);
            continue;
        }

        /* TODO - check here CNTSUM */

        PRINT("Original Name:   %s\n", s_fh.orig_path );
        PRINT("Target Name:     %s\n", s_fh.target_path );
        PRINT("File Size:       %i\n", (INT) w_stat_size(s_fh.stat));
        PRINT("Size in update   %i\n", (FH_FILE_SIZE_TYPE) s_fh.size);
        PRINT("Major:		    %i\n", s_fh.major);
        PRINT("Minor: 		    %i\n", s_fh.minor);
        PRINT("Description:     %s\n", s_fh.description);
        PRINT("Flags:%Xl\n", (unsigned) s_fh.flags);
        PRINT("Flags:     ");

        if ( CHECK_FLAG(s_fh.flags,UPD_INSTALL_PATH) )
        {
            PRINT(" UPD_INSTALL_PATH");
        }
        if (CHECK_FLAG(s_fh.flags,UPD_INSTALL_FORCE))
        {
            PRINT(" UPD_INSTALL_FORCE");
        }
        if (CHECK_FLAG(s_fh.flags,UPD_INSTALL_TARGET))
        {
            PRINT(" UPD_INSTALL_TARGET");
        }
        if (CHECK_FLAG(s_fh.flags,UPD_BACKUP))
        {
            PRINT(" UPD_BACKUP");
        }

        PRINT("\n");
        PRINT("---------------------------------------------\n");

        /* rv = lseek(fd, offset - sizeof(fh),SEEK_CUR); */
        i_rv = w_lseek(ps_fd , s_fh.size , W_SEEK_CUR);

    } while (i_offset < w_stat_size(ps_st) && i_rv > 0); 


    w_close( ps_fd );
    w_free_stat(ps_st);

    RETURN( 0 );

}



/*
FUNCTION: 	print_header
IN:			file name
OUT:		status

Get file name.
Validates to be update packet.
If ok print header and exit.

 */

    #if(0)
struct packet_header 
{
    CHAR control_sum[PACKET_CNTSUM_SIZE];     /* Control sum of whole package */
    CHAR magic[PACKET_MAGIC_SIZE];                /* A magic word */
    PACKET_MAJOR_TYPE major;                      /* Package major */
    PACKET_MINOR_TYPE minor;                      /* Package minor */
    PACKET_FLAGS_TYPE flags;                      /* Package flags */
    PACKET_VERSION_TYPE version;                  /* Version of packager */
    CHAR name[PACKET_NAME_SIZE];                  /* Name of the package */
    CHAR description[PACKET_DESCRIPTION_SIZE];    /* Description of whole package */
    CHAR reserved[PACKET_RESERVED_SIZE];          /* Reserved for user */
};
    #endif



INT print_header(CHAR * pc_file_name)
{
    FD_T * ps_fd;
    /* TODO: eplace stat by wrappe "touch_file" */
    STAT_T * ps_st;
    INT i_rv;

    packet_header_t s_ph;

    ENTRY();
    ps_st = w_new_stat();
    if (NULL == ps_st)
    {
        PERROR("");
        RETURN( - 1 );
    }
    if (pc_file_name == NULL)
    {
        RETURN( - EINVAL );
    }

    /* Clean */
    w_memset (&s_ph, 0, sizeof (packet_header_t));


    /* Stat file before open */
    i_rv = w_stat(pc_file_name, ps_st);
    if (i_rv < 0 )
    {
        w_free_stat(ps_st);
        PERROR("stat is wrong !");
        RETURN( i_rv );
    }

    /* Open asked file */
    ps_fd = w_open (pc_file_name, W_O_RDONLY);

    if ( w_filestatus( ps_fd ) < 0 )
    {
        w_free_stat(ps_st);
        PERROR("Can't open file");
        RETURN( - EIO );
    }

    /* Read header */

    i_rv = w_read(ps_fd, (CHAR *) &s_ph, sizeof(packet_header_t));

    if (i_rv != sizeof(packet_header_t))
    {

        PERROR("Can't read update's header");
    }

    /* Test singature fields */

    /* TODO - */
/*
  if ( CHECK_SINGATURE(&fh_update.singature) != 0) {
    PRINT("Wrong singature of update\n");

    RETURN( - ECANCELED );
  }
 */


    /* In the case of common header "path" field it is NAME of package */
    PRINT("Updater version: %i\n", s_ph.version);

    PRINT("Update name: %s\n", s_ph.name);


    if (CHECK_FLAG(s_ph.flags, UPD_HAS_PREINSTALL))
    {
        PRINT("Update has install script\n");
    }

    PRINT("Update major-minor: %i-%i\n", (int) s_ph.major, (int) s_ph.minor);
    PRINT("Update description: %s\n", s_ph.description);


    w_close( ps_fd );
    w_free_stat(ps_st);
    RETURN( 0 );
}

#endif /* BE_VERBOSE */
